package com.example.ruiji.config.shiro;

import ch.qos.logback.classic.turbo.TurboFilter;
import com.example.ruiji.filter.JwtTokenFilter;
import com.example.ruiji.filter.JwtTokenFilter2;
import com.example.ruiji.utils.token.JwtToken;
import com.example.ruiji.utils.token.MyTokenUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.mgt.SubjectDAO;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import java.util.LinkedHashMap;

/**
 * Author:BaiYiChen
 * Date:2022/5/2 20:20
 *
 * @author BaiYiChen
 */
@Configuration
public class ShiroConfig {
  @Bean
  public Realm realm(){
    
    return new Realm();
  }
  @Bean
  public JwtTokenCredentialsMatcher credentialsMatcher(){
    
    return new JwtTokenCredentialsMatcher();
  }
  @Bean("mySubjectDao")
  public SubjectDAO subjectDAO(){
    DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
    DefaultWebSessionStorageEvaluator sessionStorageEvaluator = new DefaultWebSessionStorageEvaluator();
    sessionStorageEvaluator.setSessionStorageEnabled(false);
    subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);
    
    return subjectDAO;
  }
  
  @Bean
  public DefaultWebSecurityManager defaultWebSecurityManager(Realm realm,@Qualifier("mySubjectDao") SubjectDAO subjectDAO,JwtTokenCredentialsMatcher credentialsMatcher){
    realm.setCredentialsMatcher(credentialsMatcher);
    DefaultWebSecurityManager webSecurityManager = new DefaultWebSecurityManager(realm);
    webSecurityManager.setSubjectDAO(subjectDAO);
    return webSecurityManager;
  }
  
  @Bean
  public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager webSecurityManager){
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(webSecurityManager);
  
    LinkedHashMap<String, Filter> linkedHashMap = new LinkedHashMap<>();
    linkedHashMap.put("jwtTokenFilter", new JwtTokenFilter());
    shiroFilterFactoryBean.setFilters(linkedHashMap);
    
    LinkedHashMap<String, String> linkedHashMap1 = new LinkedHashMap<>();
    linkedHashMap1.put("/static/**", "anon");
    linkedHashMap1.put("/login.do", "anon");
    linkedHashMap1.put("/login", "anon");
    linkedHashMap1.put("/**", "jwtTokenFilter");
    
    
    shiroFilterFactoryBean.setFilterChainDefinitionMap(linkedHashMap1);
    
    shiroFilterFactoryBean.setLoginUrl("/login");
    shiroFilterFactoryBean.setUnauthorizedUrl("/login");
  
    return shiroFilterFactoryBean;
  }
  
}

class Realm extends AuthorizingRealm{
  @Override
  public boolean supports(AuthenticationToken token) {
    return token instanceof JwtToken;
  }
  
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    return null;
  }
  
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    JwtToken token=(JwtToken) authenticationToken;
    
    String accessToken = token.getPrincipal().toString();
    String account = MyTokenUtils.getAccount(accessToken);
    String salt = MyTokenUtils.getSalt(accessToken);
    System.out.println(account+salt+":"+accessToken);
    
    try{
      MyTokenUtils.verifiedToken(accessToken, account, salt);
    }catch (Exception e){
      System.out.println("AuthenticationInfo:验证不通过");
      return null;
    }
    return new SimpleAuthenticationInfo(accessToken, authenticationToken, getName());
  }
}

class JwtTokenCredentialsMatcher  implements CredentialsMatcher {
  
  @Override
  public boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo authenticationInfo) {
    String accessToken = authenticationInfo.getPrincipals().toString();
    String orignal = authenticationToken.getPrincipal().toString();
    if(orignal.equals(accessToken)){
      return true;
    }
    return false;
  }
}
